﻿using BCCommon;
using BCCommon.TMS.Driver;
using BCData.TMS.Driver.DriverExamine;
using BCData.TMS.Driver.DriverLearnDatum;
using BCDto.Sim.Admin.Admin;
using BCDto.TMS.Driver.DriverExamine;
using BCDto.TMS.Driver.DriverLearnDatum;
using BCEntity.TMS.Driver.DriverExamine;
using BCEntity.TMS.Driver.DriverLearnDatum;
using BCService.Utils;
using System;
using System.Collections.Generic;
using System.Linq;

namespace BCService.TMS.Driver.DriverLearnDatum
{
    public class DriverLearnDatumService : IDriverLearnDatumService
    {
        protected readonly IDriverLearnDatumData driverLearnDatumData;
        protected readonly IDriverLearnDatumAnswerData learnDatumAnswerData;
        protected readonly IDriverExamineTestQuestionAnswerData questionAnswerData;
        protected readonly IDriverExamineTestQuestionData testQuestionData;
        protected readonly IRedisService redisService;
        protected readonly string entityName = "DriverLearnDatumEntity";

        public DriverLearnDatumService(IDriverLearnDatumData driverLearnDatumData,
            IDriverExamineTestQuestionData testQuestionData,
            IDriverLearnDatumAnswerData learnDatumAnswerData,
            IDriverExamineTestQuestionAnswerData questionAnswerData,
            IRedisService redisService)
        {
            this.driverLearnDatumData = driverLearnDatumData;
            this.learnDatumAnswerData = learnDatumAnswerData;
            this.questionAnswerData = questionAnswerData;
            this.testQuestionData = testQuestionData;
            this.redisService = redisService;
        }

        public DriverLearnDatumAnswerViewDto Add(AdminDto admin, DriverLearnDatumRequestDto dto)
        {
            DriverLearnDatumAnswerViewDto result = new DriverLearnDatumAnswerViewDto();
            DriverLearnDatumEntity entity = new DriverLearnDatumEntity();
            int correctAnswerId = default(int);
            int maxNo = questionAnswerData.GetMaxTestquestionNo();
            maxNo = maxNo == default(int) ? 1 : maxNo + 1;

            if (dto.Answers.Where(s => s.IsCorrect).Count() > 1)
            {
                throw new ArgumentException("单选题学习资料只能有一个正确答案。");
            }
            List<DriverExamineTestQuestionAnswerDto> answerLists = new List<DriverExamineTestQuestionAnswerDto>();
            answerLists.Clear();
            for (int i = 0; i < dto.Answers.Length; i++)
            {
                var answer = dto.Answers[i];

                DriverLearnDatumAnswerEntity answerEntity = new DriverLearnDatumAnswerEntity();
                DriverExamineTestQuestionAnswerEntity questionAnswerEntity = new DriverExamineTestQuestionAnswerEntity
                {
                    TestquestionNo = maxNo.ToString()
                };
                answerEntity.AnswerContent = answer.AnswerContent;
                answerEntity.CreateTime = DateTime.Now;
                answerEntity.ModifyAdminId = admin.AdminId;
                answerEntity.ModifyDateTime = DateTime.Now;
                if (answer.IsCorrect)
                {
                    correctAnswerId = learnDatumAnswerData.InsertAsync(answerEntity).GetAwaiter().GetResult();
                    questionAnswerEntity.DatumAnswerId = correctAnswerId;
                }
                else
                {
                    int datumAnswerId = learnDatumAnswerData.InsertAsync(answerEntity).GetAwaiter().GetResult();
                    questionAnswerEntity.DatumAnswerId = datumAnswerId;
                }
                questionAnswerEntity.AnswerContent = answer.AnswerContent;
                questionAnswerEntity.TIndex = i + 1;
                var newQuestionAnswerId = questionAnswerData.InsertAsync(questionAnswerEntity).GetAwaiter().GetResult();
                if (newQuestionAnswerId > 0)
                {
                    DriverExamineTestQuestionAnswerDto answerDto = new DriverExamineTestQuestionAnswerDto
                    {
                        AnswerContent = questionAnswerEntity.AnswerContent,
                        TestquestionNo = questionAnswerEntity.TestquestionNo,
                        DatumAnswerId = questionAnswerEntity.DatumAnswerId,
                        IsCorrect = answer.IsCorrect
                    };
                    answerLists.Add(answerDto);
                }
            }
            entity.DatumTopic = dto.DatumTopic;
            entity.DatumAnswerId = correctAnswerId;
            entity.CreateTime = DateTime.Now;
            entity.ModifyAdminId = admin.AdminId;
            entity.ModifyDateTime = DateTime.Now;
            entity.AppliedTo = dto.AppliedTo;

            var newEntity = driverLearnDatumData.InsertAsync(entity).GetAwaiter().GetResult();
            if (newEntity != null)
            {
                result.LearnDatum = newEntity.As<DriverLearnDatumDto>();
                result.Answers = answerLists.ToArray();
            }
            return result;
        }

        public bool Delete(int datumId)
        {
            if (!driverLearnDatumData.CheckExistsByIdAsync(datumId).GetAwaiter().GetResult())
            {
                throw new ArgumentException("DatumIdNotExists");
            }

            //删除试题信息
            IEnumerable<DriverExamineTestQuestionEntity> testQuestions = testQuestionData.GetDriverExamineTestQuestionsByDatumId(datumId).GetAwaiter().GetResult();
            if (testQuestions.Any())
            {
                var deleteQuestionCounts = testQuestionData.DeleteByDatumIds(testQuestions.Select(s => s.DatumId).ToArray()).GetAwaiter().GetResult();
            }

            IEnumerable<DriverExamineTestQuestionAnswerEntity> questionAnswers = questionAnswerData.GetTestQuestionAnswerByDaturnAnswerIds(new int[] { datumId }).GetAwaiter().GetResult();
            if (questionAnswers.Any())
            {
                string[] testquestionsNos = questionAnswers.GroupBy(s => s.TestquestionNo).Select(s => s.First().TestquestionNo).ToArray();
                var tempAnswers = questionAnswerData.GetDriverExamineTestQuestionAnswersByQuestionsNos(testquestionsNos).GetAwaiter().GetResult();
                //删除考试题答案信息
                if (testquestionsNos.Any())
                {
                    questionAnswerData.DeleteByTestquestionNos(testquestionsNos).GetAwaiter().GetResult();
                }
                bool result = driverLearnDatumData.DeleteAsync(datumId).GetAwaiter().GetResult();
                if (result)
                {
                    string key = string.Format("{0}@DatumId:{1}", entityName, datumId);
                    redisService.Delete(key);
                }
                //删除学习资料答案
                if (tempAnswers.Any())
                {
                    int[] datumAnswerIds = tempAnswers.Select(s => s.DatumAnswerId).ToArray();
                    if (datumAnswerIds.Length > 0)
                    {
                        learnDatumAnswerData.DeleteByDatumAnswerIdsAsync(datumAnswerIds).GetAwaiter().GetResult();
                    }
                }
                if (!result)
                {
                    throw new ArgumentException("学习资料删除失败");
                }
                return result;
            }
            return false;
        }

        public DriverLearnDatumAnswerViewDto DriverLearnDatumByDatumIdWithAnswer(int datumId)
        {
            DriverLearnDatumAnswerViewDto result = new DriverLearnDatumAnswerViewDto();
            if (!driverLearnDatumData.CheckExistsByIdAsync(datumId).GetAwaiter().GetResult())
            {
                throw new ArgumentException("DatumIdNotExists");
            }
            DriverLearnDatumEntity learnDatumEntity = driverLearnDatumData.GetDriverLearnDatumByIdAsync(datumId).GetAwaiter().GetResult();
            List<DriverExamineTestQuestionAnswerDto> answerLists = new List<DriverExamineTestQuestionAnswerDto>();
            answerLists.Clear();
            //获取学习资料答案
            var rightAnswer = questionAnswerData.GetTestQuestionAnswerByDaturnAnswerIds(new int[] { datumId }).GetAwaiter().GetResult().FirstOrDefault();
            if (rightAnswer != null)
            {
                IEnumerable<DriverExamineTestQuestionAnswerEntity> answers = questionAnswerData.GetDriverExamineTestQuestionAnswersByQuestionsNos(new string[] { rightAnswer.TestquestionNo }).GetAwaiter().GetResult();
                if (answers.Any())
                {
                    foreach (var item in answers)
                    {
                        DriverExamineTestQuestionAnswerDto answer = new DriverExamineTestQuestionAnswerDto();
                        answer.AnswerContent = item.AnswerContent;
                        answer.DatumAnswerId = item.DatumAnswerId;
                        answer.TestquestionNo = item.TestquestionNo;
                        answer.TIndex = item.TIndex;
                        answer.IsCorrect = item.DatumAnswerId == rightAnswer.DatumAnswerId;
                        answerLists.Add(answer);
                    }
                }
            }
            if (learnDatumEntity != null && answerLists.Any())
            {
                result.LearnDatum = learnDatumEntity.As<DriverLearnDatumDto>();
                result.Answers = answerLists.ToArray();
            }
            return result;
        }

        public DriverLearnDatumDto GetDriverLearnDatumById(int datumId)
        {
            string key = string.Format("{0}@DatumId:{1}", entityName, datumId);

            var entity = this.redisService.TryGet(key, () => driverLearnDatumData.GetDriverLearnDatumByIdAsync(datumId)).GetAwaiter().GetResult();

            return entity.As<DriverLearnDatumDto>();
        }


        public PageableList<DriverLearnDatumDto> GetDriverLearnDatums(string datumTopic, string answerContent, DriverRoleType? appliedTo, int pageIndex, int pageSize)
        {
            var queryResult = driverLearnDatumData.GetDriverLearnDatumsAsync(datumTopic, answerContent, appliedTo, pageIndex, pageSize).GetAwaiter().GetResult();
            return new PageableList<DriverLearnDatumDto>
            {
                Items = queryResult.Item1.As<IEnumerable<DriverLearnDatumDto>>(),
                Count = queryResult.Item2,
                PageIndex = pageIndex,
                PageSize = pageSize
            };
        }
    }
}
